import functools
import json

from flask import (
    Blueprint, current_app, flash, g, redirect, render_template, request, session, url_for,Response,abort,jsonify
)
from werkzeug.security import check_password_hash, generate_password_hash

from flaskr.db import get_db

from flask_cors import *

bp = Blueprint('nucleic-acid', __name__, url_prefix='/')

cors=CORS(bp,supports_credentials=True)

@bp.route('/nucleic-acid-test', methods=['GET', 'POST'])
def nucleic_acid_test():
    if request.method == 'POST':
        if(session.get('permission') != 'User'):
            abort(403)
        data = request.get_data()    
        data = json.loads(data.decode("utf-8"))
        medical_point_id = data['medical_point_id']
        time = data['time']
        db = get_db()
        appointment_id = db.execute(
            'SELECT appointment_id FROM User WHERE id = ?', (session.get('id'),)
            ).fetchone()
        if(appointment_id['appointment_id'] >= 0):
            res = Response(f"您有核酸预约未完成")
            abort(res)
        try:
            db.execute(
                "UPDATE Medical_point set nucleic_acid = nucleic_acid - 1 , nucleic_acid_waiting = nucleic_acid_waiting + 1 where id = ?",
                (medical_point_id,),
            )
            db.execute(
                "INSERT INTO Nucleic_acid_record (user_id, medical_point_id, status, time) VALUES (?, ?, ?, ?)",
                (session.get('id'), medical_point_id, 3, time),
            )
            db.commit()
            db.execute(
                "UPDATE User set appointment_id = ? where id = ?", 
                (int(medical_point_id),session.get('id'),),
            )
            db.commit()
        except db.IntegrityError:
            res = Response("医疗点不存在")
            abort(res)
        else:
            current_app.logger.info("User: "+str(session.get('id'))+" make nucleic_acid_appointment to "+str(medical_point_id))
            return "success"
            
    elif request.method == 'GET':
        if(session.get('permission') != 'User'):
            abort(403)
        username = session.get('id')
        db = get_db()
        test_records = db.execute(
            'SELECT time,status,username FROM Nucleic_acid_record join Medical_point WHERE medical_point_id = Medical_point.id and user_id = ? ORDER BY time DESC', (username,)
        ).fetchall()
        record_list = []
        for record in test_records:
            record_list.append({'username':record['username'],'time':record['time'],'result':record['status']})
        return jsonify({'record_list':record_list})
    abort(405)  #method not allowed

@bp.route('/nucleic-acid-add', methods=['GET','POST'])
def nucleic_acid_add():
    db = get_db()
    if request.method == 'POST':
        data = request.get_data()    
        data = json.loads(data.decode("utf-8"))
        number = data['number']
        if int(number) < 0:
            abort(400)
        if(session.get('permission') != 'Medical_point'):
            abort(403)
        try:
            db.execute(
                "UPDATE Medical_point set nucleic_acid = nucleic_acid + ? where id = ?",
                (number,session.get('id'),),
            )
            db.commit()
        except db.IntegrityError:
            abort(400)
        else:
            current_app.logger.info("Medical_point: "+str(session.get('id'))+" add nucleic_acid "+str(number))
            return "success"
    elif request.method == 'GET':
        number = db.execute(
            'SELECT nucleic_acid FROM Medical_point WHERE id = ?', (session.get('id'),)
            ).fetchone()[0]
        return jsonify({'number':number})
    abort(405)

@bp.route('/nucleic-acid-record', methods=['GET','POST'])
def nucleic_acid_record():
    db = get_db()
    if request.method == 'POST':
        if(session.get('permission') != 'Medical_point'):
            abort(403)
        data = request.get_data()    
        data = json.loads(data.decode("utf-8"))
        record_ID = data['record_id']
        name = data['username']
        result = data['result']
        appointment_id = db.execute(
            'SELECT appointment_id FROM User WHERE username = ?', (name,)
            ).fetchone()
        if(appointment_id['appointment_id'] == record_ID):
            try:
                db.execute(
                    "UPDATE User set appointment_id = -1 WHERE username = ?",
                    (name,),
                )
                db.commit()
            except db.IntegrityError:
                abort(400)
        test_records = db.execute(
            'SELECT medical_point_id,status FROM Nucleic_acid_record WHERE id = ?', (record_ID,)
            ).fetchone()
        if(test_records['status'] == 3 and result != 3):
            try:
                db.execute(
                    "UPDATE Medical_point set nucleic_acid_waiting = nucleic_acid_waiting - 1 where id = ?",
                    (test_records['medical_point_id'],),
                )
                db.execute(
                    "UPDATE User set appointment_id = -1 WHERE username = ?",
                    (name,),
                )
                db.commit()
            except db.IntegrityError:
                abort(400)    
        try:
            db.execute(
                "UPDATE Nucleic_acid_record set status = ? where id = ?",
                (result,record_ID,),
            )
            db.commit()
        except db.IntegrityError:
            abort(400)
        if(result == 0 or result == 1):
            try:
                db.execute(
                    "UPDATE User set status = ? WHERE id = ?",
                    (result,session.get('id'),),
                )
                db.commit()
            except db.IntegrityError:
                abort(400)
        current_app.logger.info("Medical_point: "+str(session.get('id'))+" update nucleic_acid "+str(record_ID) + " to " + str(result))
        return "success"
    elif request.method == 'GET':
        if(session.get('permission') == 'Medical_point'):
            db = get_db()
            test_records = db.execute(
                'SELECT Nucleic_acid_record.id,username,time,Nucleic_acid_record.status FROM Nucleic_acid_record join User WHERE medical_point_id = ? and (Nucleic_acid_record.status = 3 or Nucleic_acid_record.status = 2) and user_id = User.id', (session.get('id'),)
            ).fetchall()
            record_list = []
            for record in test_records:
                record_list.append({'id':record['id'], 'username':record['username'],'time':record['time'],'result':record['status']})
            return jsonify({'record_list':record_list})
        abort(403)
        
@bp.route('/nucleic-acid-cancel', methods=['DELETE'])
def nucleic_acid_cancel():
    if request.method == 'DELETE':
        if(session.get('permission') != 'User'):
            abort(403)
        db = get_db()
        appointment_id = db.execute(
            'SELECT appointment_id FROM user WHERE id = ?', (session.get('id'),)
            ).fetchone()
        if(appointment_id['appointment_id'] >= 0):
            appointment = db.execute(
                'SELECT id FROM Nucleic_acid_record WHERE medical_point_id = ? and user_id = ? and status = 3', (appointment_id['appointment_id'],session.get('id'),)
                ).fetchone()
            try:
                db.execute(
                    "DELETE FROM Nucleic_acid_record WHERE id = ?",
                    (appointment['id'],),
                )
                db.execute(
                    "UPDATE User set appointment_id = -1 WHERE id = ?",
                    (session.get('id'),),
                )
                db.execute(
                    "UPDATE Medical_point set nucleic_acid = nucleic_acid + 1 , nucleic_acid_waiting = nucleic_acid_waiting - 1 where id = ?",
                    (appointment_id['appointment_id'],),
                )
                db.commit()
            except db.IntegrityError:
                abort(400)
            else:
                current_app.logger.info("User: "+str(session.get('id'))+" cancel nucleic_acid_appointment "+str(appointment['id']))
                return "success"
        res = Response("当前无未完成预约")
        abort(res)
    abort(405)
